import 'dart:async';
import 'dart:math';

import 'package:async/async.dart';
import 'package:async_test/src/utils.dart';

import '../common/test_page.dart';

class CancelableOperationTestPage extends TestPage {
  CancelableOperationTestPage(super.title) {
    group('CancelableCompleter而不会被取消', () {
      late CancelableCompleter completer;
      setUp() {
        completer = CancelableCompleter(onCancel: () {});
      }

      test(
          'CancelableCompleter(onCancel: () {}).operation.value, .isCompleted, .complete()向未来发送值',
              () {
            setUp();
            expect(completer.operation.value);
            expect(completer.isCompleted);
            completer.complete(1);
            expect(completer.isCompleted);
          });

      test('将空值发送到未来', () {
        setUp();
        expect(completer.operation.value);
        expect(completer.isCompleted);
        completer.complete(null);
        expect(completer.isCompleted);
      });

      test('将错误发送到未来', () {
        setUp();
        expect(completer.operation.value);
        expect(completer.isCompleted);
        completer.completeError('error');
        expect(completer.isCompleted);
      });

      test('将未来的值发送到未来', () {
        setUp();
        expect(completer.operation.value);
        expect(completer.isCompleted);
        completer.complete(Future.value(1));
        expect(completer.isCompleted);
      });

      test('将将来的错误发送到将来', () async {
        setUp();
        expect(completer.operation.value);
        expect(completer.isCompleted);
        expect(completer.operation.isCompleted);
        completer.complete(Future.error('error'));
        expect(completer.isCompleted);
        await flushMicrotasks();
        expect(completer.operation.isCompleted);
      });

      test(
          'CancelableCompleter(onCancel: () {}).completeOperation(CancelableOperation.fromFuture(Future.value(1)))将可取消操作的值发送到未来',
              () {
            setUp();
            expect(completer.operation.value);
            completer
                .completeOperation(CancelableOperation.fromFuture(Future.value(1)));
          });

      test('将已完成的可取消操作中的值发送到未来', () async {
        setUp();
        final operation = CancelableOperation.fromFuture(Future.value(1));
        await operation.value;
        expect(completer.operation.value);
        completer.completeOperation(operation);
      });

      test('将可取消操作中的错误发送到未来', () {
        setUp();
        expect(completer.operation.value);
        completer.completeOperation(
            CancelableOperation.fromFuture(Future.error('error')..ignore()));
      });

      test('将已完成的可取消操作中的错误发送到未来', () async {
        setUp();
        final operation =
        CancelableOperation.fromFuture(Future.error('error')..ignore());
        try {
          await operation.value;
        } on Object {
          // ignore
        }
        expect(completer.operation.value);
        completer.completeOperation(operation);
      });

      test(
          'CancelableCompleter(onCancel: () {}).operation.valueOrCancellation()将值发送到valueOrCancellation',
              () {
            setUp();
            expect(completer.operation.valueOrCancellation());
            completer.complete(1);
          });

      test('将错误发送到valueOrCancellation', () {
        setUp();
        expect(completer.operation.valueOrCancellation());
        completer.completeError('error');
      });

      test(
          'CancelableOperation.fromFuture(Future.value(null)).then((_) {}).value)',
              () async {
            setUp();
            var operation = CancelableOperation.fromFuture(Future.value(null));
            expect(await operation.then((_) {}).value);
          });

      test('在结果可用之前不完整', () async {
        var backingWork = Completer();
        var operation = CancelableOperation.fromFuture(backingWork.future);
        expect(operation.isCompleted);
        backingWork.complete();
        await backingWork.future;
        expect(operation.isCompleted);
      });

      test('CancelableCompleter(onCancel: () {}).complete()成功两次', () {
        setUp();
        completer.complete(1);
        expect(() => completer.complete(1));
      });

      test('成功然后失败', () {
        setUp();
        completer.complete(1);
        expect(() => completer.completeError('error'));
      });

      test('两次失败', () {
        setUp();
        expect(completer.operation.value);
        completer.completeError('error');
        expect(() => completer.completeError('error'));
      });

      test('成功，然后有了未来', () {
        setUp();
        completer.complete(1);
        expect(() => completer.complete(Completer().future));
      });

      test('有了未来，就成功了', () {
        setUp();
        completer.complete(Completer().future);
        expect(() => completer.complete(1));
      });

      test('有两次未来', () {
        setUp();
        completer.complete(Completer().future);
        expect(() => completer.complete(Completer().future));
      });

      test('放入Future.value()实现远期价值', () {
        setUp();
        var operation = CancelableOperation.fromFuture(Future.value(1));
        expect(operation.value);
      });

      test('放入Future.error()实现转发错误', () {
        setUp();
        var operation = CancelableOperation.fromFuture(Future.error('error'));
        expect(operation.value);
      });

      test('CancelableOperation.fromSubscription()完成后转发已完成的事件', () async {
        setUp();
        var controller = StreamController<void>();
        var operationCompleted = false;
        CancelableOperation.fromSubscription(controller.stream.listen(null))
            .then((_) {
          operationCompleted = true;
        });

        await flushMicrotasks();
        expect(operationCompleted);

        controller.close();
        await flushMicrotasks();
        expect(operationCompleted);

        test('CancelableOperation.fromSubscription()转发错误', () {
          var operation = CancelableOperation.fromSubscription(
              Stream.error('error').listen(null));
          expect(operation.value);
        });
      });
    });

    group('CancelableCompleter取消时', () {
      test('CancelableCompleter().operation.value未来值不改变', () async {
        var completer = CancelableCompleter();
        completer.operation.value.whenComplete(() {});
        completer.operation.cancel();

        await flushMicrotasks();
        expect(completer.operation.value);
        completer.complete();
        await flushMicrotasks();
        expect(completer.operation.value);
      });

      test('设置CancelableCompleter(onCancel: () {})测试取消时的签名变化', () {
        var canceled = false;
        late CancelableCompleter completer;
        completer = CancelableCompleter(onCancel: () {
          expect(completer.isCanceled);
          canceled = true;
        });

        expect(canceled);
        expect(completer.isCanceled);
        expect(completer.operation.isCanceled);
        expect(completer.isCompleted);
        expect(completer.operation.isCompleted);
        completer.operation.cancel();
        expect(canceled);
        expect(completer.isCanceled);
        expect(completer.operation.isCanceled);
        expect(completer.isCompleted);
        expect(completer.operation.isCompleted);
      });

      test('每次调用cancel时返回onCancel future', () {
        var completer = CancelableCompleter(onCancel: () {
          return Future.value(1);
        });
        expect(completer.operation.cancel());
        expect(completer.operation.cancel());
        expect(completer.operation.cancel());
      });

      test("返回future，即使onCancel没有", () {
        var completer = CancelableCompleter(onCancel: () {});
        expect(completer.operation.cancel());
      });

      test("如果完成器已完成，则不调用Cancel", () {
        var completer = CancelableCompleter(onCancel: () {});
        completer.complete(1);
        expect(completer.operation.value);
        expect(completer.operation.cancel());
      });

      test('如果完成者已完成未完成的Future，则调用Cancel', () {
        var completer = CancelableCompleter(onCancel: () {});
        completer.complete(Completer().future);
        expect(completer.operation.cancel());
      });

      test('如果完成器已完成激发的Future，则不调用onCancel', () async {
        var completer = CancelableCompleter(onCancel: () {});
        completer.complete(Future.value(1));
        await completer.operation.value;
        expect(completer.operation.cancel());
      });

      test('取消后可以完成一次', () async {
        var completer = CancelableCompleter();
        completer.operation.value.whenComplete(() {});
        await completer.operation.cancel();
        completer.complete(1);
        expect(() => completer.complete(1));
      });

      test('使用给定值激发valueOrCancellation', () {
        var completer = CancelableCompleter();
        expect(completer.operation.valueOrCancellation(1));
        completer.operation.cancel();
      });

      test('通过valueOrCancellation传递错误', () {
        var completer = CancelableCompleter(onCancel: () {
          throw 'error';
        });
        expect(completer.operation.valueOrCancellation(1));
        completer.operation.cancel();
      });

      test('valueOrCancellation等待onCancel未来', () async {
        var innerCompleter = Completer();
        var completer =
        CancelableCompleter(onCancel: () => innerCompleter.future);

        var fired = false;
        completer.operation.valueOrCancellation().then((_) {
          fired = true;
        });

        completer.operation.cancel();
        await flushMicrotasks();
        expect(fired);

        innerCompleter.complete();
        await flushMicrotasks();
        expect(fired);
      });

      test('CancelableOperation.fromSubscription()取消订阅', () async {
        var cancelCompleter = Completer<void>();
        var canceled = false;
        var controller = StreamController<void>(onCancel: () {
          canceled = true;
          return cancelCompleter.future;
        });
        var operation = CancelableOperation.fromSubscription(
            controller.stream.listen(null));

        await flushMicrotasks();
        expect(canceled);

        var cancelCompleted = false;
        expect(
            operation.cancel().then((_) {
              cancelCompleted = true;
            }));
        await flushMicrotasks();
        expect(canceled);
        expect(cancelCompleted);

        cancelCompleter.complete();
        await flushMicrotasks();
        expect(cancelCompleted);
      });

      test(
          'CancelableCompleter<void>().completeOperation(CancelableCompleter<void>().operation..cancel())发送可取消操作的取消',
              () async {
            final completer = CancelableCompleter<void>();
            completer.operation.value.whenComplete(() {});
            completer
                .completeOperation(CancelableCompleter<void>().operation..cancel());
            await completer.operation.valueOrCancellation();
            expect(completer.operation.isCanceled);
          });

      test('将已完成的可取消操作中的错误发送到未来', () async {
        final operation = CancelableCompleter<void>().operation..cancel();
        await operation.valueOrCancellation();
        final completer = CancelableCompleter<void>();
        completer.operation.value.whenComplete(() {});
        completer.completeOperation(operation);
        await completer.operation.valueOrCancellation();
        expect(completer.operation.isCanceled);
      });

      test('传播消除', () {
        final completer = CancelableCompleter<void>();
        final operation = CancelableCompleter<void>(onCancel: () {}).operation;
        completer.completeOperation(operation);
        expect(completer);
        completer.operation.cancel();
        expect(completer);
      });

      test('从已取消的完成符传播取消', () async {
        final completer = CancelableCompleter<void>()..operation.cancel();
        await completer.operation.valueOrCancellation();
        final operation = CancelableCompleter<void>(onCancel: () {}).operation;
        expect(completer);
        completer.completeOperation(operation);
        expect(completer);
      });
      test('可以禁用取消传播', () {
        final completer = CancelableCompleter<void>();
        final operation = CancelableCompleter<void>(onCancel: () {}).operation;
        completer.completeOperation(operation, propagateCancel: false);
        expect(completer);
        completer.operation.cancel();
        expect(completer);
      });

      test('取消传播可以从已取消状态禁用已完成', () async {
        final completer = CancelableCompleter<void>()..operation.cancel();
        await completer.operation.valueOrCancellation();
        final operation = CancelableCompleter<void>(onCancel: () {}).operation;
        expect(completer);
        completer.completeOperation(operation, propagateCancel: false);
        expect(completer);
      });
    });

    group('CancelableCompleter().operation.asStream()', () {
      test('CancelableCompleter().operation.asStream().toList()', () {
        var completer = CancelableCompleter();
        expect(completer.operation.asStream().toList());
        completer.complete(1);
        expect(completer.operation.asStream().toList());
      });

      test('CancelableCompleter().operation.asStream()发出错误，然后关闭', () {
        var completer = CancelableCompleter();
        var queue = StreamQueue(completer.operation.asStream());
        expect(queue.next);
        expect(queue.hasNext);
        completer.completeError('error');
        expect(queue.next);
      });

      test('取消订阅时取消完成器', () {
        var completer = CancelableCompleter(onCancel: () {});
        var sub = completer.operation.asStream().listen((_) {});
        completer.operation.value.whenComplete(() {});
        sub.cancel();
        expect(completer.isCanceled);
      });
    });

    group('CancelableCompleter().operation.then()', () {
      FutureOr<String> Function(int)? onValue;
      FutureOr<String> Function(Object, StackTrace)? onError;
      FutureOr<String> Function()? onCancel;
      late bool propagateCancel;
      late CancelableCompleter<int> originalCompleter;

      setUp() {
        onValue = (_) => 'Fake';
        onError = (e, s) => 'Fake';
        onCancel = () => 'Fake';
        propagateCancel = false;
        originalCompleter = CancelableCompleter();
      }

      CancelableOperation<String> runThen() {
        return originalCompleter.operation.then(onValue!,
            onError: onError,
            onCancel: onCancel,
            propagateCancel: propagateCancel);
      }

      test('CancelableCompleter().operation.then(onValue) onValue成功完成', () {
        setUp();
        onValue = (v) => v.toString();

        expect(runThen().value);
        originalCompleter.complete(1);
        expect(runThen().value);
      });

      test('onValue引发错误', () {
        setUp();
        onValue = (_) => throw 'error';

        expect(runThen().value);
        originalCompleter.complete(1);
        expect(runThen().value);
      });

      test('onValue返回引发错误的Future', () {
        setUp();
        onValue = (v) => Future.error('error');

        expect(runThen().value);
        originalCompleter.complete(1);
        expect(runThen().value);
      });

      test('返回的操作被取消，propagateCancel=false', () async {
        setUp();
        propagateCancel = false;

        runThen().cancel();
        expect(runThen().value);

        originalCompleter.complete(1);
        expect(runThen().value);
      });

      test('onError未设置', () {
        setUp();
        onError = null;

        expect(runThen().value);
        originalCompleter.completeError('error');
        expect(runThen().value);
      });

      test('onError成功完成', () {
        setUp();
        onError = (e, s) => 'onError caught $e';

        expect(runThen().value);
        originalCompleter.completeError('error');
        expect(runThen().value);
      });

      test('onError引发', () {
        setUp();
        onError = (e, s) => throw 'onError caught $e';

        expect(runThen().value);
        originalCompleter.completeError('error');
        expect(runThen().value);
      });

      test('onError返回抛出的Future', () {
        setUp();
        onError = (e, s) => Future.error('onError caught $e');

        expect(runThen().value);
        originalCompleter.completeError('error');
        expect(runThen().value);
      });

      test('返回的操作被取消，propagateCancel=false', () async {
        setUp();
        propagateCancel = false;

        runThen().cancel();
        expect(runThen().value);

        originalCompleter.completeError('error');
        expect(runThen().value);
      });

      test('onCancel未设置', () async {
        setUp();
        onCancel = null;

        final operation = runThen();

        expect(originalCompleter.operation.cancel());
        expect(operation.isCanceled);
      });

      test('onCancel取消成功完成', () {
        setUp();
        onCancel = () => 'canceled';

        expect(runThen().value);
        originalCompleter.operation.cancel();
        expect(runThen().value);
      });

      test('onCancel引发错误', () {
        setUp();
        onCancel = () => throw 'error';

        expect(runThen().value);
        originalCompleter.operation.cancel();
        expect(runThen().value);
      });

      test('onCancel返回引发错误的Future', () {
        setUp();
        onCancel = () => Future.error('error');

        expect(runThen().value);
        originalCompleter.operation.cancel();
        expect(runThen().value);
      });

      test('使用future完成后不调用onValue', () async {
        setUp();
        onValue = (_) => '';
        onCancel = null;
        var operation = runThen();
        var workCompleter = Completer<int>();
        originalCompleter.complete(workCompleter.future);
        var cancelation = originalCompleter.operation.cancel();
        expect(originalCompleter.isCanceled);
        workCompleter.complete(0);
        await cancelation;
        expect(operation.isCanceled);
        await workCompleter.future;
      });

      test('值完成后调用`onValue`', () {
        setUp();
        onValue = (_) => 'foo';
        onCancel = () => '';
        originalCompleter.complete(0);
        originalCompleter.operation.cancel();
        var operation = runThen();
        expect(operation.value);
        expect(operation.isCanceled);
      });

      test('等待连锁取消', () async {
        setUp();
        var completer = CancelableCompleter<void>();
        var chainedOperation = completer.operation
            .then((_) => Future.delayed(Duration(milliseconds: 1)))
            .then((_) => Future.delayed(Duration(milliseconds: 1)));

        await completer.operation.cancel();
        expect(completer.operation.isCanceled);
        expect(chainedOperation.isCanceled);
      });

      test('propagateCancel = true', () async {
        setUp();
        propagateCancel = true;

        await runThen().cancel();

        expect(originalCompleter.isCanceled);
      });

      test('propagateCancel = false', () async {
        setUp();
        propagateCancel = false;

        await runThen().cancel();

        expect(originalCompleter.isCanceled);
      });

      test('取消后未调用onValue回调', () async {
        setUp();
        var called = false;
        onValue = (_) {
          called = true;
          return 'onValue unreachable';
        };

        await runThen().cancel();
        originalCompleter.complete(0);
        await flushMicrotasks();
        expect(called);
      });

      test('取消后未调用onError回调', () async {
        setUp();
        var called = false;
        onError = (_, __) {
          called = true;
          return 'onError unreachable';
        };

        await runThen().cancel();
        originalCompleter.completeError('Error', StackTrace.empty);
        await flushMicrotasks();
        expect(called);
      });

      test('取消后未调用onCancel回调', () async {
        setUp();
        var called = false;
        onCancel = () {
          called = true;
          return 'onCancel unreachable';
        };

        await runThen().cancel();
        await originalCompleter.operation.cancel();
        await flushMicrotasks();
        expect(called);
      });
    });

    group('CancelableCompleter().operation.thenOperation()', () {
      late void Function(int, CancelableCompleter<String>) onValue;
      void Function(Object, StackTrace, CancelableCompleter<String>)? onError;
      void Function(CancelableCompleter<String>)? onCancel;
      late bool propagateCancel;
      late CancelableCompleter<int> originalCompleter;

      setUp() {
        onValue = (value, completer) => completer.complete('$value');
        onError = null;
        onCancel = null;
        propagateCancel = false;
        originalCompleter = CancelableCompleter();
      }

      CancelableOperation<String> runThenOperation() {
        return originalCompleter.operation.thenOperation(onValue,
            onError: onError,
            onCancel: onCancel,
            propagateCancel: propagateCancel);
      }

      test('onValue成功完成', () {
        setUp();
        onValue = (v, c) => c.complete('$v');

        expect(runThenOperation().value);
        originalCompleter.complete(1);
        expect(runThenOperation().value);
      });

      test('onValue引发错误', () {
        setUp();
        onValue = (_, __) => throw 'error';

        expect(runThenOperation().value);
        originalCompleter.complete(1);
        expect(runThenOperation().value);
      });

      test('onValue作为错误完成操作', () {
        setUp();
        onValue = (_, completer) => completer.completeError('error');

        expect(runThenOperation().value);
        originalCompleter.complete(1);
        expect(runThenOperation().value);
      });

      test('onValue返回引发错误的Future', () {
        setUp();
        onValue = (_, completer) => Future.error('error');

        expect(runThenOperation().value);
        originalCompleter.complete(1);
        expect(runThenOperation().value);
      });

      test('返回的操作被取消', () async {
        setUp();
        onValue = (_, __) => throw 'never called';
        runThenOperation().cancel();
        expect(runThenOperation().value);
        originalCompleter.complete(1);
        expect(runThenOperation().value);
      });

      test('onError未设置', () {
        setUp();
        onError = null;

        expect(runThenOperation().value);
        originalCompleter.completeError('error');
        expect(runThenOperation().value);
      });

      test('onError完成操作', () {
        setUp();
        onError = (e, s, c) => c.complete('onError caught $e');

        expect(runThenOperation().value);
        originalCompleter.completeError('error');
        expect(runThenOperation().value);
      });

      test('onError引发', () {
        setUp();
        onError = (e, s, c) => throw 'onError caught $e';

        expect(runThenOperation().value);
        originalCompleter.completeError('error');
        expect(runThenOperation().value);
      });

      test('onError返回引发错误的Future', () {
        setUp();
        onError = (e, s, c) => Future.error('onError caught $e');

        expect(runThenOperation().value);
        originalCompleter.completeError('error');
        expect(runThenOperation().value);
      });

      test('onError作为错误完成操作', () {
        setUp();
        onError = (e, s, c) => c.completeError('onError caught $e');

        expect(runThenOperation().value);
        originalCompleter.completeError('error');
        expect(runThenOperation().value);
      });

      test('返回的操作被取消，propagateCancel=false', () async {
        setUp();
        onError = (e, s, c) {};

        runThenOperation().cancel();
        expect(runThenOperation().value);

        originalCompleter.completeError('error');
        expect(runThenOperation().value);
      });

      test('onCancel未设置', () async {
        setUp();
        onCancel = null;

        final operation = runThenOperation();

        expect(originalCompleter.operation.cancel());
        expect(operation.isCanceled);
      });

      test('onCancel成功完成', () {
        setUp();
        onCancel = (c) => c.complete('canceled');

        expect(runThenOperation().value);
        originalCompleter.operation.cancel();
        expect(runThenOperation().value);
      });

      test('onCancel引发错误', () {
        setUp();
        onCancel = (_) => throw 'error';

        expect(runThenOperation().value);
        originalCompleter.operation.cancel();
        expect(runThenOperation().value);
      });

      test('onCancel作为错误完成操作', () {
        setUp();
        onCancel = (c) => c.completeError('error');

        expect(runThenOperation().value);
        originalCompleter.operation.cancel();
        expect(runThenOperation().value);
      });

      test('onCancel返回引发错误的Future', () {
        setUp();
        onCancel = (c) => Future.error('error');

        expect(runThenOperation().value);
        originalCompleter.operation.cancel();
        expect(runThenOperation().value);
      });

      test('使用future完成后不调用`onValue`', () async {
        setUp();
        onValue = (_, __) {};
        onCancel = null;
        var operation = runThenOperation();
        var workCompleter = Completer<int>();
        originalCompleter.complete(workCompleter.future);
        var cancelation = originalCompleter.operation.cancel();
        expect(originalCompleter.isCanceled);
        workCompleter.complete(0);
        await cancelation;
        expect(operation.isCanceled);
        await workCompleter.future;
      });

      test('值完成后调用`onValue`', () {
        setUp();
        onValue = (v, c) => c.complete('foo');
        onCancel = (_) {};
        originalCompleter.complete(0);
        originalCompleter.operation.cancel();
        var operation = runThenOperation();
        expect(operation.value);
        expect(operation.isCanceled);
      });

      test('propagateCancel = true', () async {
        setUp();
        propagateCancel = true;

        await runThenOperation().cancel();

        expect(originalCompleter.isCanceled);
      });

      test('propagateCancel = false', () async {
        setUp();
        propagateCancel = false;

        await runThenOperation().cancel();

        expect(originalCompleter.isCanceled);
      });

      test('取消后未调用onValue回调', () async {
        setUp();
        onValue = (_, c) {};

        await runThenOperation().cancel();
        expect(runThenOperation().value);
        originalCompleter.complete(0);
      });

      test('取消后未调用onError回调', () async {
        setUp();
        onError = (_, __, ___) {};

        await runThenOperation().cancel();
        expect(runThenOperation().value);
        originalCompleter.completeError('Error', StackTrace.empty);
      });

      test('取消后未调用onCancel回调', () async {
        setUp();
        onCancel = (_) {};

        await runThenOperation().cancel();
        expect(runThenOperation().value);
        await originalCompleter.operation.cancel();
      });
    });

    group('CancelableOperation.race()', () {
      late bool canceled1;
      late CancelableCompleter<int> completer1;
      late bool canceled2;
      late CancelableCompleter<int> completer2;
      late bool canceled3;
      late CancelableCompleter<int> completer3;
      late CancelableOperation<int> operation;
      setUp() {
        canceled1 = false;
        completer1 = CancelableCompleter<int>(onCancel: () {
          canceled1 = true;
        });

        canceled2 = false;
        completer2 = CancelableCompleter<int>(onCancel: () {
          canceled2 = true;
        });

        canceled3 = false;
        completer3 = CancelableCompleter<int>(onCancel: () {
          canceled3 = true;
        });

        operation = CancelableOperation.race(
            [completer1.operation, completer2.operation, completer3.operation]);
      }

      test('返回要完成的第一个值', () {
        setUp();
        completer1.complete(1);
        completer2.complete(2);
        completer3.complete(3);

        expect(operation.value);
      });

      test('抛出要完成的第一个错误', () {
        setUp();
        completer1.completeError('error 1');
        completer2.completeError('error 2');
        completer3.completeError('error 3');

        expect(operation.value);
      });

      test('取消所有尚未完成的完成符', () async {
        setUp();
        completer1.complete(1);
        expect(operation.value);
        expect(canceled1);
        expect(canceled2);
        expect(canceled3);
      });

      test('CancelableOperation.race().cancel()操作完成后取消所有完成符', () async {
        setUp();
        await operation.cancel();

        expect(canceled1);
        expect(canceled2);
        expect(canceled3);
      });
    });
  }
}